Search: make universal results mode-aware#658
Conversation
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughUniversal search now supports mode-aware requests, specifier results, preferred-domain ordering, saved favourites, and cross-mode “also matches” surfaces across search pages and dashboards. Client caching, API validation, dropdown behavior, navigation, and UI tests are updated. ChangesUniversal search foundation
Command surface and saved favourites
Cross-mode result surfaces
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant SearchSurface
participant UniversalSearchAPI
participant runUniversalSearch
participant AlsoMatches
User->>SearchSurface: enter query and select mode
SearchSurface->>UniversalSearchAPI: request query with mode
UniversalSearchAPI->>runUniversalSearch: run context-aware search
runUniversalSearch-->>UniversalSearchAPI: ordered domain groups
UniversalSearchAPI-->>SearchSurface: mode-specific results
SearchSurface->>AlsoMatches: render query and current mode
AlsoMatches-->>User: show matches in other modes
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 01f587db85
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex resolve actionable Codex review findings for this pull request and current head using the repository instructions. This is the pull request's single automatic repair pass: do not perform a fresh review, create new standalone findings, or request another review. Work only the existing unresolved Codex threads on the current head. Always fix P0 and P1 findings. For P2 and lower findings, fix only clear, scoped, low-risk issues; otherwise disposition them with a concise reason. After fixing or dispositioning a thread, reply in that thread with as the first line, followed by a concise summary; that marker authorizes the workflow to close that exact thread. If human input or new authorization is required, do not use the marker and leave the thread open with the blocker. Finish only after every actionable thread is fixed or dispositioned and closed, or explicitly left open for a human decision. Do not update the branch from main, address unrelated reviews, broaden scope, or create more than one scoped fix commit. Do not use external APIs, paid services, credentials, dependency changes, or broad refactors unless explicitly authorized. Add targeted tests where behavior changes and run the narrowest relevant validation. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 01f587db85
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
CI triageCI failed on this PR. Automated classification of the 3 failed job(s):
Heuristic only — a main-side or flake label is a starting point, not a verdict. |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/clinical-dashboard/use-universal-search.ts (1)
192-219: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win"fresh" fallback ignores
contextMode, allowing stale wrong-mode results to render as fresh.
fresh(Line 208) only comparesresult.query === trimmedQuery; it doesn't checkresult.contextMode === args.contextMode. When the active mode changes but the query stays the same, and the new (query, mode) combo isn't already cached, this hook returns the previous mode'sgroups,domainOrder,preferredDomains,topHit, andanswerActionasloading: falseuntil the debounced refetch resolves — i.e. every consumer (universal-search-command-surface.tsx,universal-search-also-matches.tsxinsearch-results-header-band.tsx/specifiers-home-page.tsx) can briefly render/rank results computed for the wrong mode. This undermines the mode-aware ordering that is the point of this PR, in a clinical decision-support surface.The cached-snapshot path (Lines 194-207) is unaffected since
cacheKeyalready encodescontextMode; only this fallback needs the fix.🐛 Proposed fix
- const fresh = result.query === trimmedQuery; + const fresh = result.query === trimmedQuery && result.contextMode === args.contextMode;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/clinical-dashboard/use-universal-search.ts` around lines 192 - 219, Update the `fresh` check in the fallback result path to require both `result.query === trimmedQuery` and `result.contextMode === args.contextMode`. Keep the cached-snapshot branch unchanged, and continue returning empty or undefined result fields with `loading: true` whenever either query or context mode does not match.
🧹 Nitpick comments (2)
src/components/clinical-dashboard/universal-search-command-surface.tsx (2)
32-44: 📐 Maintainability & Code Quality | 🔵 TrivialStale comment references a removed mapping.
This comment still says "Reverse of
modeIdByDomain", but per this same change that mapping was removed and replaced byuniversalSearchModeForDomain(imported at line 30). The comment is now misleading to future readers ofdomainsByTargetMode.✏️ Suggested comment fix
-// Reverse of modeIdByDomain for chip counts: the domains whose live result totals a -// cross-mode chip should sum. Answer/favourites chips have no countable domain; the +// Domains whose live result totals a cross-mode chip should sum. Answer/favourites +// chips have no countable domain; the // differentials chip counts both of its domains because the mode home search composes // presentations and diagnoses into one result list.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/clinical-dashboard/universal-search-command-surface.tsx` around lines 32 - 44, Update the comment above domainsByTargetMode to reference universalSearchModeForDomain instead of the removed modeIdByDomain mapping, while preserving the existing explanation of cross-mode chip domain aggregation.
57-106: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
standaloneis a fragile proxy derived fromprimaryAction === "Run".
rankLocalFavouritesgates cross-mode visibility (visibleFavouriteMatchesat line 481-482) on this heuristic: only saved searches (primaryAction === "Run") and favourite sets are ever shown outside Favourites mode; individual saved items (medications/documents/sources withprimaryActionlike"Open"/"Ask"/"Source"/"Copy") never surface as "Also in Favourites". This may be intentional (avoiding duplicate entity display since those already surface via their native domain), but it's undocumented and relies on exact string equality against an unrelatedFavouriteItem.primaryActionfield rather than an explicit flag — a future favourite with a newprimaryActionvalue would silently be excluded from cross-mode display with no compile-time signal.Consider adding a short comment explaining the intent, or promoting this to an explicit field on
FavouriteItem(e.g.crossModeVisible) so the contract is discoverable at the type level.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/clinical-dashboard/universal-search-command-surface.tsx` around lines 57 - 106, Document the cross-mode visibility contract in rankLocalFavourites: standalone should identify saved searches and favourite sets, while individual saved entities remain excluded because they already appear through native domain results. Prefer adding an explicit FavouriteItem field such as crossModeVisible and use it instead of comparing primaryAction to "Run"; otherwise add a concise comment explaining the intentional proxy.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/ClinicalDashboard.tsx`:
- Around line 3581-3591: Update the render guard around
UniversalSearchAlsoMatches so Answer mode remains eligible when
latestAnswerQuery is populated, even after query is cleared. Use the same
effective query selection as the component prop—latestAnswerQuery ?? query—for
the non-empty check, while preserving the existing result-kind restrictions and
behavior for Tools and Favourites.
---
Outside diff comments:
In `@src/components/clinical-dashboard/use-universal-search.ts`:
- Around line 192-219: Update the `fresh` check in the fallback result path to
require both `result.query === trimmedQuery` and `result.contextMode ===
args.contextMode`. Keep the cached-snapshot branch unchanged, and continue
returning empty or undefined result fields with `loading: true` whenever either
query or context mode does not match.
---
Nitpick comments:
In `@src/components/clinical-dashboard/universal-search-command-surface.tsx`:
- Around line 32-44: Update the comment above domainsByTargetMode to reference
universalSearchModeForDomain instead of the removed modeIdByDomain mapping,
while preserving the existing explanation of cross-mode chip domain aggregation.
- Around line 57-106: Document the cross-mode visibility contract in
rankLocalFavourites: standalone should identify saved searches and favourite
sets, while individual saved entities remain excluded because they already
appear through native domain results. Prefer adding an explicit FavouriteItem
field such as crossModeVisible and use it instead of comparing primaryAction to
"Run"; otherwise add a concise comment explaining the intentional proxy.
🪄 Autofix (Beta)
❌ Autofix failed (check again to retry)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 579ca0f7-b7ae-44d3-8b67-41a4a4da5bf4
📒 Files selected for processing (18)
src/app/api/search/universal/route.tssrc/components/ClinicalDashboard.tsxsrc/components/clinical-dashboard/search-results-header-band.tsxsrc/components/clinical-dashboard/universal-search-also-matches.tsxsrc/components/clinical-dashboard/universal-search-command-surface.tsxsrc/components/clinical-dashboard/use-universal-search.tssrc/components/services/services-navigator-page.tsxsrc/components/specifiers/specifiers-home-page.tsxsrc/lib/app-modes.tssrc/lib/search-command-surface.tssrc/lib/universal-search-domains.tssrc/lib/universal-search-mode-context.tssrc/lib/universal-search.tstests/app-modes.test.tstests/search-command-surface.test.tstests/ui-tools.spec.tstests/ui-universal-search.spec.tstests/universal-search.test.ts
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e53686c6bd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4395a97809
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7fe8ab6951
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@copilot resolve the merge conflicts on this branch. |
Head branch was pushed to by a user without write access
…h-mode-ranking # Conflicts: # src/components/formulation/formulation-home-page.tsx # src/lib/app-modes.ts
…ing' into codex/universal-search-mode-ranking # Conflicts: # src/components/formulation/formulation-home-page.tsx # src/lib/app-modes.ts
…ing' into codex/universal-search-mode-ranking
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 972d45ea5b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. Autofix skipped. No unresolved CodeRabbit review comments with fix instructions found. |
Summary
Why
The shared composer was visually universal but did not consistently search or rank all mode-owned content. Queries now remain mode-aware without hiding strong matches from other modes.
Areas touched
Universal search API/contract, mode/domain ownership, command surface, submitted result summaries, Favourites client index, Specifiers/Tools configuration, and focused Vitest/Playwright coverage.
Verification
npm run verify:pr-local -- --files <18 universal-search files>— passed on the current merged tipChecks not run
No live search evaluation, owner-live test, Supabase/OpenAI provider check, hosted release check, or production data operation was run. Production readiness in the isolated worktree remains environment-blocked by absent Supabase/OpenAI variables.
Production/governance
No database migration or production environment change. Favourites remain client-local and are never sent to the universal-search API. Existing owner/public scoping and partial-failure behavior are preserved.
Summary by CodeRabbit